import { Button } from "@renderer/components/ui/base/button";
import { FieldGroup, Input } from "@renderer/components/ui/base/field";
import { Select } from "@renderer/components/ui/base/select";
import {
  Tab,
  TabList,
  TabPanel,
  Tabs,
} from "@renderer/components/ui/base/tabs";
import { cn } from "@renderer/lib/utils";
import logger from "@shared/logger/renderer-logger";
import {
  ChevronLeft,
  Download,
  FolderOpen,
  RefreshCw,
  Search,
  Trash2,
} from "lucide-react";
import { motion } from "motion/react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";

interface LogEntry {
  timestamp: string;
  level: string;
  message: string;
  context?: string;
}

interface LogFile {
  date: string;
  level: string;
  path: string;
  size: number;
  entries: LogEntry[];
}

const { filePreviewService } = window.service;

export function LogViewer() {
  const { t } = useTranslation("translation", {
    keyPrefix: "settings.log-viewer",
  });
  const navigate = useNavigate();

  const [logFiles, setLogFiles] = useState<LogFile[]>([]);
  const [selectedDate, setSelectedDate] = useState<string>("");
  const [selectedLevel, setSelectedLevel] = useState<string>("error");
  const [isLoading, setIsLoading] = useState(false);
  const [currentLog, setCurrentLog] = useState<LogFile | null>(null);
  const [searchTerm, setSearchTerm] = useState<string>("");

  const logLevels = [
    { value: "error", label: "Error", color: "text-red-500" },
    { value: "warn", label: "Warning", color: "text-yellow-500" },
    { value: "info", label: "Info", color: "text-blue-500" },
    { value: "debug", label: "Debug", color: "text-gray-500" },
  ];

  const loadLogFiles = useCallback(async () => {
    setIsLoading(true);
    try {
      const files = await filePreviewService.getLogFiles();
      setLogFiles(files);

      if (files.length > 0 && !selectedDate) {
        setSelectedDate(files[0].date);
      }
    } catch (error) {
      logger.error("Failed to load log files", { error });
    } finally {
      setIsLoading(false);
    }
  }, [selectedDate]);

  const loadLogContent = useCallback(async (date: string, level: string) => {
    setIsLoading(true);
    try {
      const content = await filePreviewService.readLogFile(date, level);
      setCurrentLog(content);
    } catch (error) {
      logger.error("Failed to load log content", { error, date, level });
    } finally {
      setIsLoading(false);
    }
  }, []);

  const handleBack = () => {
    navigate("/settings/about-settings");
  };

  const handleDownload = async () => {
    if (!currentLog) return;
    try {
      await filePreviewService.previewFileByPath(currentLog.path);
      logger.info("Log file downloaded", { path: currentLog.path });
    } catch (error) {
      logger.error("Failed to download log file", {
        error,
        path: currentLog.path,
      });
    }
  };

  const handleOpenDirectory = async () => {
    try {
      const result = await filePreviewService.openLogDirectory();
      if (result.success) {
        logger.info("Log directory opened successfully");
      } else {
        logger.error("Failed to open log directory", { error: result.error });
      }
    } catch (error) {
      logger.error("Failed to open log directory", { error });
    }
  };

  const handleClearLogs = async () => {
    try {
      const result = await filePreviewService.clearLogs();
      if (result.success) {
        logger.info("Logs cleared successfully");
        await loadLogFiles();
      } else {
        logger.error("Failed to clear logs", { error: result.error });
      }
    } catch (error) {
      logger.error("Failed to clear logs", { error });
    }
  };

  const handleRefresh = () => {
    loadLogFiles();
    if (selectedDate && selectedLevel) {
      loadLogContent(selectedDate, selectedLevel);
    }
  };

  useEffect(() => {
    loadLogFiles();
  }, [loadLogFiles]);

  useEffect(() => {
    if (selectedDate && selectedLevel) {
      loadLogContent(selectedDate, selectedLevel);
    }
  }, [selectedDate, selectedLevel, loadLogContent]);

  // Filter log entries based on search term
  const filteredLogEntries = useMemo(() => {
    if (!currentLog || !searchTerm.trim()) {
      return currentLog?.entries || [];
    }

    const searchLower = searchTerm.toLowerCase();
    return currentLog.entries.filter(
      (entry) =>
        entry.message.toLowerCase().includes(searchLower) ||
        entry.level.toLowerCase().includes(searchLower) ||
        entry.timestamp.toLowerCase().includes(searchLower) ||
        entry.context?.toLowerCase().includes(searchLower),
    );
  }, [currentLog, searchTerm]);

  const availableDates = [...new Set(logFiles.map((f) => f.date))]
    .sort()
    .reverse();

  return (
    <motion.div
      initial={{ opacity: 0, rotateY: 360, scale: 0.8 }}
      animate={{ opacity: 1, rotateY: 0, scale: 1 }}
      transition={{
        duration: 1.0,
        ease: "easeInOut",
        type: "spring",
        stiffness: 100,
        damping: 15,
      }}
      className="flex h-full flex-col p-6"
    >
      {/* Header */}
      <div className="mb-6 flex items-center justify-between">
        <div className="flex items-center gap-4">
          <Button
            intent="secondary"
            size="sm"
            onPress={handleBack}
            className="flex items-center gap-2"
          >
            <ChevronLeft size={16} />
            {t("back-to-about")}
          </Button>
          <h1 className="font-semibold text-2xl">{t("title")}</h1>
        </div>

        <div className="flex items-center gap-2">
          <Button
            intent="secondary"
            size="sm"
            onPress={handleRefresh}
            isDisabled={isLoading}
          >
            <RefreshCw size={16} className={cn(isLoading && "animate-spin")} />
          </Button>
          <Button intent="secondary" size="sm" onPress={handleOpenDirectory}>
            <FolderOpen size={16} />
          </Button>
          <Button
            intent="secondary"
            size="sm"
            onPress={handleDownload}
            isDisabled={!currentLog}
          >
            <Download size={16} />
          </Button>
          <Button intent="danger" size="sm" onPress={handleClearLogs}>
            <Trash2 size={16} />
          </Button>
        </div>
      </div>

      {/* Filters */}
      <div className="mb-4 space-y-4">
        <div className="flex items-center gap-4">
          <div className="flex items-center gap-2">
            <span className="whitespace-nowrap font-medium text-sm">
              {t("date")}:
            </span>
            <Select
              selectedKey={selectedDate}
              onSelectionChange={(key) => setSelectedDate(key as string)}
            >
              <Select.Trigger className="w-40">
                <span>{selectedDate || t("select-date")}</span>
              </Select.Trigger>
              <Select.List>
                {availableDates.map((date) => (
                  <Select.Option key={date} id={date}>
                    {date}
                  </Select.Option>
                ))}
              </Select.List>
            </Select>
          </div>

          <div className="flex items-center gap-2">
            <span className="whitespace-nowrap font-medium text-sm">
              {t("level")}:
            </span>
            <Select
              selectedKey={selectedLevel}
              onSelectionChange={(key) => setSelectedLevel(key as string)}
            >
              <Select.Trigger className="w-32">
                <span
                  className={
                    logLevels.find((l) => l.value === selectedLevel)?.color
                  }
                >
                  {logLevels.find((l) => l.value === selectedLevel)?.label}
                </span>
              </Select.Trigger>
              <Select.List>
                {logLevels.map((level) => (
                  <Select.Option key={level.value} id={level.value}>
                    <span className={level.color}>{level.label}</span>
                  </Select.Option>
                ))}
              </Select.List>
            </Select>
          </div>
        </div>

        {/* Search */}
        <div className="flex items-center gap-2">
          <Search size={16} className="text-muted-fg" />
          <FieldGroup className="max-w-md flex-1">
            <Input
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              placeholder={t("search-placeholder")}
            />
          </FieldGroup>
        </div>
      </div>

      {/* Log Content */}
      <div className="flex-1 overflow-hidden">
        <Tabs
          selectedKey={selectedLevel}
          onSelectionChange={(key) => setSelectedLevel(key as string)}
          className="h-full"
        >
          <TabList className="mb-4">
            {logLevels.map((level) => (
              <Tab
                key={level.value}
                id={level.value}
                className="flex items-center gap-2"
              >
                <span
                  className={cn(
                    "size-2 rounded-full",
                    level.color.replace("text-", "bg-"),
                  )}
                />
                {level.label}
              </Tab>
            ))}
          </TabList>

          {logLevels.map((level) => (
            <TabPanel
              key={level.value}
              id={level.value}
              className="h-[calc(100%-3rem)] overflow-hidden"
            >
              <div className="h-full overflow-y-auto rounded-lg border bg-background p-4 font-mono text-sm">
                {isLoading ? (
                  <div className="flex h-32 items-center justify-center">
                    <RefreshCw className="animate-spin" size={20} />
                    <span className="ml-2">{t("loading")}</span>
                  </div>
                ) : currentLog && currentLog.level === level.value ? (
                  <div className="space-y-2">
                    {filteredLogEntries.length > 0 ? (
                      filteredLogEntries.map((entry, index) => (
                        <div
                          key={`${entry.timestamp}-${index}`}
                          className="flex flex-col border-border border-b pb-2 last:border-b-0"
                        >
                          <div className="flex items-center gap-4 text-muted-fg text-xs">
                            <span className="whitespace-nowrap">
                              {entry.timestamp}
                            </span>
                            <span
                              className={cn(
                                "whitespace-nowrap rounded px-2 py-0.5 font-medium text-xs",
                                level.color,
                                level.color
                                  .replace("text-", "bg-")
                                  .replace("500", "100"),
                              )}
                            >
                              {entry.level}
                            </span>
                          </div>
                          <div className="mt-1">{entry.message}</div>
                          {entry.context && (
                            <div className="mt-1 text-muted-fg text-xs">
                              {entry.context}
                            </div>
                          )}
                        </div>
                      ))
                    ) : (
                      <div className="flex h-32 items-center justify-center text-muted-fg">
                        {searchTerm
                          ? t("no-search-results")
                          : t("no-logs-available")}
                      </div>
                    )}
                  </div>
                ) : (
                  <div className="flex h-32 items-center justify-center text-muted-fg">
                    {t("no-logs-available")}
                  </div>
                )}
              </div>
            </TabPanel>
          ))}
        </Tabs>
      </div>
    </motion.div>
  );
}
